#include "ports.h"
#include "string.h"
#include "debug.h"
#include "elf.h"

elf_t elf_from_multiboot(multiboot_t *mb)
{
    int i;
    elf_t elf;
    elf_section_header_t *sh = (elf_section_header_t *)mb->addr;
    uint32_t shstrtab = sh[mb->shndx].addr;
    for (i = 0; i < mb->num; i++)
    {
        // 在GRUB提供的multiboot信息中寻找内核ELF文件所提取的字符串表和符号表
        // 下面是段名称
        const char *name = (const char *)(shstrtab) + sh[i].name;
        if (strcmp(name, ".strtab") == 0)
        {
            elf.strtab = (const char *)sh[i].addr;
            elf.strtabsz = sh[i].size;
        }
        if (strcmp(name, ".symtab") == 0)
        {
            elf.symtab = (elf_symbol_t *)sh[i].addr;
            elf.symtabsz = sh[i].size;
        }
    }
    return elf;
}

const char *elf_lookup_symbol(uint32_t addr, elf_t *elf)
{
    int i;
    int count = elf->symtabsz / sizeof(elf_symbol_t);
    const char *func_name;
    for (i = 0; i < count; i++)
    {
        // 不是函数
        if (ELF32_ST_TYPE(elf->symtab[i].info) != 0x2)
        {
            continue;
        }
        // 查找函数名称
        // 地址在函数的符号表内
        if (addr >= elf->symtab[i].value && addr < (elf->symtab[i].value + elf->symtab[i].size))
        {
            func_name = (const char *)((uint32_t)elf->strtab + elf->symtab[i].name);
            return func_name;
        }
    }
    return NULL;
}